package com.ruoyi.service.Impl;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConstants;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.ruoyi.common.core.utils.uuid.UUID;
import com.ruoyi.config.PaymentEvent;
import com.ruoyi.domain.*;
import com.ruoyi.mapper.AlipayNewMapper;
import com.ruoyi.service.AlipayNewService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

@Slf4j
@Service
public class AlipayNewServiceImpl implements AlipayNewService {
    @Autowired
    private AlipayClient alipayClient;

    @Autowired
    private Environment config;
    @Autowired
    private AlipayNewMapper alipayNewMapper;
    @Autowired
    private ApplicationContext applicationContext;  // 注入 ApplicationContext

    @Override
    @Transactional
    public String tradeCreate(Pay pay) throws Exception {

        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        //支付宝公共参数
        //request.setNotifyUrl("");
        request.setReturnUrl(config.getProperty("alipay.return-url"));

        //生成订单号 年月日+4位随机数
        // 获取当前年月日
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        String dateStr = dateFormat.format(new Date());

        // 生成4位随机数
        Random random = new Random();
        int randomNum = random.nextInt(9000) + 1000; // 1000-9999
        String paymentId = dateStr + randomNum;

        //面向对象封装业务参数
        AlipayTradePagePayModel model =new AlipayTradePagePayModel();
        model.setOutTradeNo(paymentId);
        model.setTotalAmount(pay.getTotalAmount());
        model.setSubject(pay.getSubject());
        model.setProductCode(pay.getProductCode());

        //bizContent.put("time_expire", "2022-08-01 22:00:00");

        //JSONArray goodsDetail = new JSONArray();
        //JSONObject goods1 = new JSONObject();
        //goods1.put("goods_id", "goodsNo1");
        //goods1.put("goods_name", "子商品1");
        //goods1.put("quantity", 1);
        //goods1.put("price", 0.01);
        //goodsDetail.add(goods1);
        //bizContent.put("goods_detail", goodsDetail);

        //JSONObject extendParams = new JSONObject();
        //extendParams.put("sys_service_provider_id", "2088511833207846");
        //bizContent.put("extend_params", extendParams);

        //request.setBizContent(bizContent.toString());
        request.setBizModel(model);
        //执行请求,调用支付宝
        AlipayTradePagePayResponse response = alipayClient.pageExecute(request);
        if (response.isSuccess()) {
            log.info("调用成功,返回结果:[{}]",response.getBody());
            Payment payment = new Payment();
            payment.setPaymentId(paymentId);
            payment.setUserId(pay.getUserId());
            payment.setAmount(pay.getTotalAmount());
            payment.setStatus("0");
            payment.setCreateTime(new Date());
            int insert = alipayNewMapper.Insert(payment);
            return response.getBody();
        } else {
            log.info("调用失败!!");
        }
        return null;
    }
    @Override
    public String tradeNotify(Map<String, String> params) {
        String result = "failure";
        try {
            //异步通知验签
            boolean signVerified = AlipaySignature.rsaCheckV1(params,
                    config.getProperty("alipay.alipay-public-key"),
                    AlipayConstants.CHARSET_UTF8,
                    AlipayConstants.SIGN_TYPE_RSA2);
            if (!signVerified) {
                //  验签失败则记录异常日志，并在response中返回failure.
                log.error("支付成功,异步通知验签失败!");
                return result;
            }
            log.info("支付成功,异步通知验签成功!");
            // 验签成功后，按照支付结果异步通知中的描述，对支付结果中的业务内容进行二次校验
            //1.验证out_trade_no 是否为商家系统中创建的订单号
            String outTradeNo = params.get("out_trade_no");
            //2.判断 total_amount 是否确实为该订单的实际金额
            String totalAmount = params.get("total_amount");
            //3.校验通知中的 seller_id是否为 out_trade_no 这笔单据的对应的操作方
            String sellerId = params.get("seller_id");
            if (!sellerId.equals(config.getProperty("alipay.seller-id"))) {
                log.error("商家PID校验失败");
                return result;
            }
            //4.验证 app_id 是否为该商家本身
            String appId = params.get("app_id");
            if (!appId.equals(config.getProperty("alipay.app.id"))){
                log.error("app_id校验失败");
                return result;
            }
            //在支付宝的业务通知中，只有交易通知状态为 TRADE_SUCCESS 或 TRADE_FINISHED 时，支付宝才会认定为买家付款成功
            String tradeStatus = params.get("trade_status");
            if (!"TRADE_SUCCESS".equals(tradeStatus) && !"TRADE_FINISHED".equals(tradeStatus)){
                log.error("支付未成功");
                return result;
            }

            //TODO 处理自身业务
            alipayNewMapper.UpdateStatus(outTradeNo);

            result = "success";
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }

        return result;
    }

    @Override
    @Transactional
    public String tradeReturn(HttpServletRequest request) throws AlipayApiException {
        // 1. 将请求参数转为 Map<String, String>
        Map<String, String> params = convertRequestParamsToMap(request);

        // 2. 验证支付宝同步回调签名
        boolean signVerified = AlipaySignature.rsaCheckV1(
                params,
                config.getProperty("alipay.alipay-public-key"),
                AlipayConstants.CHARSET_UTF8,
                AlipayConstants.SIGN_TYPE_RSA2
        );

        if (!signVerified) {
            log.error("支付宝同步回调验签失败，疑似非法请求！参数：{}", params);
            return "redirect:/payment-error"; // 跳转至支付失败页面
        }

        // 3. 解析关键参数（需校验业务参数）
        String appId = params.get("app_id");
        String outTradeNo = params.get("out_trade_no");
        String totalAmount = params.get("total_amount");

        // 4. 校验支付宝应用ID是否匹配
        if (!config.getProperty("alipay.app.id").equals(appId)) {
            log.error("支付宝AppID校验失败，请求AppID: {}", appId);
            return "redirect:/payment-error";
        }

        // 5. 将string转为bigdecimal
        alipayNewMapper.UpdateStatus(outTradeNo);
        BigDecimal totalAmountDecimal = new BigDecimal(totalAmount);
        // bigdecimal*100怎么计算转为long
        long points = totalAmountDecimal.multiply(new BigDecimal(100)).longValue();
        Long userId = alipayNewMapper.selectUserFromPayment(outTradeNo);
        Point point = alipayNewMapper.selectUserFromPoint(userId);
        if(point == null){
            point = new Point();
            point.setPoints(points);
            point.setUserId(userId);
            int resultAdd = alipayNewMapper.addPoint(point);
            // 添加到order表中
            Orders order = new Orders();
            order.setUserId(userId);
            order.setPoints(points);
            order.setOriginalPoints(0L);
            order.setCurrentPoints(points);
            order.setType(1);
            order.setCreateTime(new Date());
            alipayNewMapper.InsertOders(order);
        }else {
            // 添加到order表中
            Orders order = new Orders();
            order.setUserId(userId);
            order.setPoints(points);
            // 修改积分表
            points = point.getPoints() + points;
            int resultUpdate = alipayNewMapper.updatePoint(userId,points);

            order.setOriginalPoints(point.getPoints());
            order.setCurrentPoints(points);
            order.setType(1);
            order.setCreateTime(new Date());
            alipayNewMapper.InsertOders(order);
        }

        // 7. 跳转到支付成功页面
        return "http://localhost/points/points";
    }

    /**
     * 将 HttpServletRequest 中的参数转为 Map<String, String>
     */
    private Map<String, String> convertRequestParamsToMap(HttpServletRequest request) {
        Map<String, String> params = new HashMap<>();
        request.getParameterMap().forEach((key, values) -> {
            if (values != null && values.length > 0) {
                params.put(key, values[0]);
            }
        });
        return params;
    }
}
